/*
@auther fenglei
*/
package xxutil

import (
	"fmt"
	"io/fs"
	"os"
	"path/filepath"
	"strings"

	"github.com/duke-git/lancet/v2/cryptor"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gookit/goutil/fsutil"
)

// 获取文件的Md5
func FileMd5(filePath string) string {
	md5Str, err := cryptor.Md5File(filePath)
	if err != nil {
		return ""
	}
	return md5Str
}

// 只获取文件名,不含后辍
func FileMainName(path string) string {
	base := filepath.Base(path)
	if i := strings.LastIndexByte(base, '.'); i != -1 {
		return base[:i]
	}
	return base
}

// 获取目录的大小Mb
func DirSizeMb(path string) (int64, error) {
	if !gfile.Exists(path) {
		return 0, fmt.Errorf("路径不存在:%s", path)
	}
	count, err := DirSize(path)
	if err != nil {
		return 0, fmt.Errorf("统计错误:%s", err)
	}
	mbSize := count / (1024 * 1024)
	if count > 0 && mbSize == 0 {
		mbSize = 1
	}
	return mbSize, nil
}

// 获取目录的大小
func DirSize(dirPath string) (int64, error) {
	var size int64
	err := fsutil.WalkDir(dirPath, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.Type().IsRegular() {
			fileInfo, err := d.Info()
			if err != nil {
				return err
			}
			if fileInfo.Mode()&os.ModeSymlink == 0 { // 确保不是符号链接
				size += fileInfo.Size()
			}
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return size, nil
}

// 文件内容替换
func ContentReplace(path string, oldStr, newStr string) error {
	cStr := gfile.GetContents(path)
	nStr := strings.ReplaceAll(cStr, oldStr, newStr)
	return gfile.PutContents(path, nStr)
}

// DeleteDir 删除指定目录及其中的所有内容（文件和子目录）
// 如果目录不存在，返回 nil（视为删除成功）
// 如果目录存在但无法删除，返回错误
func DelFileOrDir(dir string) error {
	// 检查目录是否存在
	_, err := os.Stat(dir)
	if os.IsNotExist(err) {
		// 目录不存在，视为删除成功
		return nil
	}
	if err != nil {
		// 其他错误（例如无权限访问）
		return fmt.Errorf("无法获取目录信息: %w", err)
	}
	// 直接使用 os.RemoveAll 删除整个目录树
	err = os.RemoveAll(dir)
	if err != nil {
		return fmt.Errorf("删除目录失败: %w", err)
	}
	// 检查目录是否确实已被删除
	_, err = os.Stat(dir)
	if !os.IsNotExist(err) {
		return fmt.Errorf("目录似乎没有被成功删除")
	}
	return nil
}

// DeleteDirContent 删除目录中的所有内容，但保留目录本身
// 如果目录不存在，返回错误
func DeleteDirContent(dir string) error {
	// 检查目录是否存在
	d, err := os.Open(dir)
	if err != nil {
		return fmt.Errorf("无法打开目录: %w", err)
	}
	defer d.Close()

	// 获取目录中的所有条目
	names, err := d.Readdirnames(-1)
	if err != nil {
		return fmt.Errorf("无法读取目录内容: %w", err)
	}

	// 遍历并删除每个条目
	for _, name := range names {
		err = os.RemoveAll(filepath.Join(dir, name))
		if err != nil {
			return fmt.Errorf("删除 %s 失败: %w", name, err)
		}
	}

	return nil
}

// DelFileOrDirWithParent 删除指定文件或目录，如果父目录变空则同时删除父目录
// 这个函数会先删除指定的文件或目录，然后检查其父目录是否为空
// 如果父目录为空，则也会删除父目录
func DelFileOrDirWithParent(path string) error {
	// 获取父目录路径
	parentDir := filepath.Dir(path)
	// 首先删除指定的文件或目录
	err := DelFileOrDir(path)
	if err != nil {
		return fmt.Errorf("删除文件或目录失败: %w", err)
	}
	// 安全检查：不删除根目录、当前目录或系统重要目录
	if parentDir == "." || parentDir == "/" || parentDir == filepath.VolumeName(parentDir) || parentDir == path {
		return nil
	}
	// 检查父目录是否存在
	if !gfile.Exists(parentDir) {
		return nil
	}
	// 检查父目录是否为空
	entries, err := os.ReadDir(parentDir)
	if err != nil {
		return fmt.Errorf("无法读取父目录: %w", err)
	}
	// 如果父目录为空，删除它
	if len(entries) == 0 {
		err = os.Remove(parentDir)
		if err != nil {
			return fmt.Errorf("删除父目录失败: %w", err)
		}
	}
	return nil
}
